home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / lame_src / Dll / BladeMP3EncDLL.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-01  |  11.3 KB  |  471 lines

  1. /*
  2.  *    Blade DLL Interface for LAME.
  3.  *
  4.  *    Copyright (c) 1999 A.L. Faber
  5.  *
  6.  * This library is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU Lesser General Public
  8.  * License as published by the Free Software Foundation; either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  * 
  11.  * This library is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14.  * Lesser General Public License for more details.
  15.  * 
  16.  * You should have received a copy of the GNU Lesser General Public
  17.  * License along with this library; if not, write to the
  18.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19.  * Boston, MA  02111-1307, USA.
  20.  */
  21.  
  22. #include "BladeMP3EncDLL.h"
  23. #include <assert.h>
  24. #include "version.h"  
  25. #include "VbrTag.h"   
  26. #include "lame.h"
  27. /*
  28. #include "get_audio.h"
  29. #include "globalflags.h"
  30. #include "machine.h"
  31. #include "util.h"
  32. */
  33.  
  34. #ifdef _DEBUG
  35.     #define _DEBUGDLL 1
  36. #endif
  37.  
  38.  
  39. const int MAJORVERSION=1;
  40. const int MINORVERSION=11;
  41. const int CURRENT_STRUCT_VERSION=1;
  42. const int CURRENT_STRUCT_SIZE=sizeof(BE_CONFIG);
  43.  
  44.  
  45. // Local variables
  46. static int        nPsychoModel=2;
  47. static BOOL        bFirstFrame=TRUE;
  48. static DWORD    dwSampleBufferSize=0;
  49.  
  50.  
  51. #ifdef _DEBUGDLL
  52. void dump_config( char *inPath, char *outPath);
  53. #endif
  54.  
  55. lame_global_flags gf;
  56.  
  57. static void InitParams()
  58. {
  59.     bFirstFrame=TRUE;
  60.     lame_init(&gf);
  61.  
  62. }
  63.  
  64.  
  65.  
  66.  
  67. __declspec(dllexport) BE_ERR    beInitStream(PBE_CONFIG pbeConfig, PDWORD dwSamples, PDWORD dwBufferSize, PHBE_STREAM phbeStream)
  68. {
  69.     int            nDllArgC=0;
  70.     BE_CONFIG    lameConfig;
  71.  
  72.     InitParams();
  73.  
  74.     // clear out structure
  75.     memset(&lameConfig,0x00,CURRENT_STRUCT_SIZE);
  76.  
  77.     // Check if this is a regular BLADE_ENCODER header
  78.     if (pbeConfig->dwConfig!=BE_CONFIG_LAME)
  79.     {
  80.         int    nCRC=pbeConfig->format.mp3.bCRC;
  81.         int nVBR=(nCRC>>12)&0x0F;
  82.  
  83.         // Copy parameter from old Blade structure
  84.         lameConfig.format.LHV1.dwSampleRate    =pbeConfig->format.mp3.dwSampleRate;
  85.         //for low bitrates, LAME will automatically downsample for better
  86.         //sound quality.  Forcing output samplerate = input samplerate is not a good idea 
  87.         //unless the user specifically requests it:
  88.         //lameConfig.format.LHV1.dwReSampleRate=pbeConfig->format.mp3.dwSampleRate;
  89.         lameConfig.format.LHV1.nMode        =(pbeConfig->format.mp3.byMode&0x0F);
  90.         lameConfig.format.LHV1.dwBitrate    =pbeConfig->format.mp3.wBitrate;
  91.         lameConfig.format.LHV1.bPrivate        =pbeConfig->format.mp3.bPrivate;
  92.         lameConfig.format.LHV1.bOriginal    =pbeConfig->format.mp3.bOriginal;
  93.         lameConfig.format.LHV1.bCRC            =nCRC&0x01;
  94.         lameConfig.format.LHV1.bCopyright    =pbeConfig->format.mp3.bCopyright;
  95.     
  96.         // Fill out the unknowns
  97.         lameConfig.format.LHV1.dwStructSize=CURRENT_STRUCT_VERSION;
  98.         lameConfig.format.LHV1.dwStructVersion=CURRENT_STRUCT_SIZE;
  99.  
  100.         // Get VBR setting from fourth nibble
  101.         if (nVBR>0)
  102.         {
  103.             lameConfig.format.LHV1.bWriteVBRHeader=TRUE;
  104.             lameConfig.format.LHV1.bEnableVBR=TRUE;
  105.             lameConfig.format.LHV1.nVBRQuality=nVBR-1;
  106.         }
  107.  
  108.         // Get Quality from third nibble
  109.         lameConfig.format.LHV1.nQuality=(MPEG_QUALITY)((nCRC>>8)&0x0F);
  110.  
  111.     }
  112.     else
  113.     {
  114.         // Copy the parameters
  115.         memcpy(&lameConfig,pbeConfig,pbeConfig->format.LHV1.dwStructSize);
  116.     }
  117.  
  118.  
  119.     // Not used, always assign stream 1
  120.     *phbeStream=1;
  121.  
  122.  
  123.  
  124.     // --------------- Set arguments to LAME encoder -------------------------
  125.  
  126.     // Set zero argument, the filename
  127.     //strcpy(DllArgV[nDllArgC++],"LameDLLEncoder");
  128.  
  129.       switch (lameConfig.format.LHV1.nMode)
  130.     {
  131.         case BE_MP3_MODE_STEREO:
  132.             gf.mode=0;
  133.             gf.mode_fixed=1;  /* dont allow LAME to change the mode */
  134.             gf.num_channels=2;
  135.         break;
  136.         case BE_MP3_MODE_JSTEREO:
  137.             gf.mode=1;
  138.             gf.mode_fixed=1;
  139.             gf.num_channels=2;
  140.         break;
  141.         case BE_MP3_MODE_MONO:
  142.             gf.mode=3;
  143.             gf.mode_fixed=1;
  144.             gf.num_channels=1;
  145.         break;
  146.         case BE_MP3_MODE_DUALCHANNEL:
  147.             gf.force_ms=1;
  148.             gf.mode=1;
  149.             gf.mode_fixed=1;
  150.             gf.num_channels=2;
  151.         break;
  152.         default:
  153.         {
  154.             char lpszError[255];
  155.             sprintf(lpszError,"Invalid lameConfig.format.LHV1.nMode, value is %d\n",lameConfig.format.LHV1.nMode);
  156.             OutputDebugString(lpszError);
  157.             return BE_ERR_INVALID_FORMAT_PARAMETERS;
  158.         }
  159.     }
  160.  
  161.     switch (lameConfig.format.LHV1.nQuality)
  162.     {
  163.         case NORMAL_QUALITY:    // Nothing special
  164.             break;
  165.         case LOW_QUALITY:        // -f flag
  166.             gf.quality=9;
  167.             break;
  168.         case HIGH_QUALITY:        // -h flag for high qualtiy
  169.             gf.quality=2;
  170.             break;
  171.         case VOICE_QUALITY:        // --voice flag for experimental voice mode
  172.             gf.lowpassfreq=12000;
  173.             gf.VBR_max_bitrate_kbps=160;
  174.             gf.no_short_blocks=1;
  175.         break;
  176.     }
  177.  
  178.     if (lameConfig.format.LHV1.bEnableVBR)
  179.     {
  180.         // 0=no vbr 1..10 is VBR quality setting -1
  181.         gf.VBR=1;
  182.         gf.VBR_q=lameConfig.format.LHV1.nVBRQuality;
  183.  
  184.         if (lameConfig.format.LHV1.bWriteVBRHeader==TRUE)
  185.         {
  186.             gf.bWriteVbrTag=TRUE;
  187.         }
  188.         else
  189.         {
  190.             gf.bWriteVbrTag=FALSE;
  191.         }
  192.     }
  193.  
  194.  
  195.  
  196.     // Set frequency
  197.     gf.in_samplerate=lameConfig.format.LHV1.dwSampleRate;
  198.  
  199.     // Set frequency resampling rate, if specified
  200.     if (lameConfig.format.LHV1.dwReSampleRate>0)
  201.         gf.out_samplerate=lameConfig.format.LHV1.dwReSampleRate;
  202.         
  203.     
  204.     // Set bitrate.  (CDex users always specify bitrate=Min bitrate when using VBR)
  205.     gf.brate=lameConfig.format.LHV1.dwBitrate;
  206.     gf.VBR_min_bitrate_kbps=gf.brate;
  207.             
  208.     // Set Maxbitrate, if specified
  209.     if (lameConfig.format.LHV1.dwMaxBitrate>0)
  210.         gf.VBR_max_bitrate_kbps=lameConfig.format.LHV1.dwMaxBitrate;
  211.     
  212.     // Set copyright flag?
  213.     if (lameConfig.format.LHV1.bCopyright)
  214.         gf.copyright=1;
  215.  
  216.     // Do we have to tag  it as non original 
  217.     if (!lameConfig.format.LHV1.bOriginal)
  218.     {
  219.         gf.original=0;
  220.     }
  221.     else
  222.     {
  223.         gf.original=1;
  224.     }
  225.  
  226.     // Add CRC?
  227.     if (lameConfig.format.LHV1.bCRC)
  228.     {
  229.         gf.error_protection=1;
  230.     }
  231.     else
  232.     {
  233.         gf.error_protection=0;
  234.     }
  235.  
  236.     gf.silent=1;  /* disable status ouput */
  237.  
  238.     // Set private bit?
  239.     if (lameConfig.format.LHV1.bPrivate)
  240.     {
  241.         gf.extension = 1;
  242.     }
  243.     else
  244.     {
  245.         gf.extension = 0;
  246.     }
  247.     
  248.     lame_init_params(&gf);    
  249.  
  250.     //LAME encoding call will accept any number of samples.  
  251.     *dwSamples=1152*gf.num_channels;
  252.  
  253.     // Set the input sample buffer size, so we know what we can expect
  254.     dwSampleBufferSize=*dwSamples;
  255.  
  256.     // Set MP3 buffer size
  257.     // conservative estimate
  258.     *dwBufferSize=1.25*(*dwSamples/gf.num_channels) + 7200;
  259.  
  260.  
  261. #ifdef _DEBUGDLL
  262.     dump_config(gf.inPath,gf.outPath);
  263. #endif
  264.  
  265.     // Everything went OK, thus return SUCCESSFUL
  266.     return BE_ERR_SUCCESSFUL;
  267. }
  268.  
  269.  
  270.  
  271. __declspec(dllexport) BE_ERR    beDeinitStream(HBE_STREAM hbeStream, PBYTE pOutput, PDWORD pdwOutput)
  272. {
  273.  
  274.     *pdwOutput = lame_encode_finish(&gf,pOutput,0);
  275.  
  276.     if (*pdwOutput<0) {
  277.         *pdwOutput=0;
  278.         return BE_ERR_BUFFER_TOO_SMALL;
  279.     }
  280.  
  281.     return BE_ERR_SUCCESSFUL;
  282. }
  283.  
  284.  
  285. __declspec(dllexport) BE_ERR    beCloseStream(HBE_STREAM hbeStream)
  286. {
  287.     // DeInit encoder
  288. //    return DeInitEncoder();
  289.     return BE_ERR_SUCCESSFUL;
  290. }
  291.  
  292.  
  293.  
  294. __declspec(dllexport) VOID        beVersion(PBE_VERSION pbeVersion)
  295. {
  296.     // DLL Release date
  297.     char lpszDate[20];
  298.     char lpszTemp[5];
  299.  
  300.  
  301.     // Set DLL interface version
  302.     pbeVersion->byDLLMajorVersion=MAJORVERSION;
  303.     pbeVersion->byDLLMinorVersion=MINORVERSION;
  304.  
  305.     // Set Engine version number (Same as Lame version)
  306.     pbeVersion->byMajorVersion=LAME_MAJOR_VERSION;
  307.     pbeVersion->byMinorVersion=LAME_MINOR_VERSION;
  308.  
  309.     // Get compilation date
  310.     strcpy(lpszDate,__DATE__);
  311.  
  312.     // Get the first three character, which is the month
  313.     strncpy(lpszTemp,lpszDate,3);
  314.     lpszTemp[3]='\0';
  315.     pbeVersion->byMonth=1;
  316.  
  317.     // Set month
  318.     if (strcmp(lpszTemp,"Jan")==0)    pbeVersion->byMonth=1;
  319.     if (strcmp(lpszTemp,"Feb")==0)    pbeVersion->byMonth=2;
  320.     if (strcmp(lpszTemp,"Mar")==0)    pbeVersion->byMonth=3;
  321.     if (strcmp(lpszTemp,"Apr")==0)    pbeVersion->byMonth=4;
  322.     if (strcmp(lpszTemp,"May")==0)    pbeVersion->byMonth=5;
  323.     if (strcmp(lpszTemp,"Jun")==0)    pbeVersion->byMonth=6;
  324.     if (strcmp(lpszTemp,"Jul")==0)    pbeVersion->byMonth=7;
  325.     if (strcmp(lpszTemp,"Aug")==0)    pbeVersion->byMonth=8;
  326.     if (strcmp(lpszTemp,"Sep")==0)    pbeVersion->byMonth=9;
  327.     if (strcmp(lpszTemp,"Oct")==0)    pbeVersion->byMonth=10;
  328.     if (strcmp(lpszTemp,"Nov")==0)    pbeVersion->byMonth=11;
  329.     if (strcmp(lpszTemp,"Dec")==0)    pbeVersion->byMonth=12;
  330.  
  331.     // Get day of month string (char [4..5])
  332.     pbeVersion->byDay=atoi(lpszDate+4);
  333.  
  334.     // Get year of compilation date (char [7..10])
  335.     pbeVersion->wYear=atoi(lpszDate+7);
  336.  
  337.     memset(pbeVersion->zHomepage,0x00,BE_MAX_HOMEPAGE);
  338.  
  339.     strcpy(pbeVersion->zHomepage,"http://www.sulaco.org/mp3/");
  340. }
  341.  
  342. __declspec(dllexport) BE_ERR    beEncodeChunk(HBE_STREAM hbeStream, DWORD nSamples, 
  343.              PSHORT pSamples, PBYTE pOutput, PDWORD pdwOutput)
  344. {
  345.  
  346.     // Encode it
  347.         int dwSamples;
  348.     dwSamples=nSamples/gf.num_channels;
  349.  
  350.     // old versions of lame_enc.dll required exactly 1152 samples
  351.     // and worked even if nSamples accidently set to 2304
  352.     // simulate this behavoir:
  353.     if (gf.num_channels==1 && nSamples == 2304)
  354.       dwSamples/=2;
  355.  
  356.     *pdwOutput=lame_encode_buffer_interleaved(&gf,pSamples,dwSamples,pOutput,0);
  357.  
  358.  
  359.     if (*pdwOutput<0) {
  360.         *pdwOutput=0;
  361.         return BE_ERR_BUFFER_TOO_SMALL;
  362.     }
  363.  
  364.     return BE_ERR_SUCCESSFUL;
  365. }
  366.  
  367.  
  368. __declspec(dllexport) BE_ERR beWriteVBRHeader(LPCSTR lpszFileName)
  369. {
  370.     if (gf.bWriteVbrTag)
  371.     {
  372.         // Calculate relative quality of VBR stream 
  373.         // 0=best, 100=worst
  374.         int nQuality=gf.VBR_q*100/9;
  375.  
  376.         // Write Xing header again
  377.         return PutVbrTag(&gf,(LPSTR)lpszFileName,nQuality);
  378.     }
  379.     return BE_ERR_INVALID_FORMAT_PARAMETERS;
  380. }
  381.  
  382.  
  383. BOOL APIENTRY DllMain(HANDLE hModule, 
  384.                       DWORD  ul_reason_for_call, 
  385.                       LPVOID lpReserved)
  386. {
  387.     switch( ul_reason_for_call )
  388.     {
  389.         case DLL_PROCESS_ATTACH:
  390. #ifdef _DEBUGDLL
  391.             OutputDebugString("Attach Process \n");
  392. #endif
  393.         break;
  394.         case DLL_THREAD_ATTACH:
  395. #ifdef _DEBUGDLL
  396.             OutputDebugString("Attach Thread \n");
  397. #endif
  398.         break;
  399.         case DLL_THREAD_DETACH:
  400. #ifdef _DEBUGDLL
  401.             OutputDebugString("Detach Thread \n");
  402. #endif
  403.         break;
  404.         case DLL_PROCESS_DETACH:
  405. #ifdef _DEBUGDLL
  406.             OutputDebugString("Detach Process \n");
  407. #endif
  408.         break;
  409.     }
  410.     return TRUE;
  411. }
  412.  
  413.  
  414. #ifdef _DEBUGDLL
  415. void dump_config( char *inPath, char *outPath)
  416. {
  417.       char strTmp[255];
  418.  
  419.     OutputDebugString("Encoding configuration:\n");
  420.  
  421.  
  422.     sprintf(strTmp,"Write VBR Header=%s\n",(gf.bWriteVbrTag)?"Yes":"No");
  423.     OutputDebugString(strTmp);
  424.  
  425.     sprintf(strTmp,"version=%d\n",gf.version);
  426.     OutputDebugString(strTmp);
  427.  
  428.  
  429.     sprintf(strTmp,"Layer=3   mode=%d  \n",gf.mode);
  430.     OutputDebugString(strTmp);
  431.  
  432.  
  433.     sprintf(strTmp,"samp frq=%.1f kHz   total bitrate=%d kbps\n",gf.in_samplerate/1000.0);
  434.     OutputDebugString(strTmp);
  435.  
  436.     sprintf(strTmp,"de-emph=%d   c/right=%d   orig=%d   errprot=%s\n",gf.emphasis, gf.copyright, gf.original,((gf.error_protection) ? "on" : "off"));
  437.     OutputDebugString(strTmp);
  438.  
  439. //    sprintf(strTmp,"16 Khz cut off is %s\n",(0)?"enabled":"disabled");
  440. //    OutputDebugString(strTmp);
  441.  
  442.     sprintf(strTmp,"Fast mode is %s\n",(gf.quality==9)?"enabled":"disabled");
  443.     OutputDebugString(strTmp);
  444.  
  445.     sprintf(strTmp,"Force ms %s\n",(gf.force_ms)?"enabled":"disabled");
  446.     OutputDebugString(strTmp);
  447.  
  448. //    sprintf(strTmp,"GPsycho acoustic model is %s\n",(gpsycho)?"enabled":"disabled");
  449. //    OutputDebugString(strTmp);
  450.  
  451.     sprintf(strTmp,"VRB is %s, VBR_q value is  %d\n",(gf.VBR)?"enabled":"disabled",gf.VBR_q);
  452.     OutputDebugString(strTmp);
  453.  
  454.     sprintf(strTmp,"input file: '%s'   output file: '%s'\n", inPath, outPath);
  455.     OutputDebugString(strTmp);
  456.  
  457. //    sprintf(strTmp,"Voice mode %s\n",(voice_mode)?"enabled":"disabled");
  458. //    OutputDebugString(strTmp);
  459.  
  460.     sprintf(strTmp,"Encoding as %.1f kHz %d kbps MPEG-%d LayerIII file\n",gf.out_samplerate/1000.0,gf.brate,gf.mode,3 - gf.version);
  461.     OutputDebugString(strTmp);
  462. }
  463.  
  464.  
  465. void DispErr(LPSTR strErr)
  466. {
  467.     MessageBox(NULL,strErr,"",MB_OK);
  468. }
  469.  
  470. #endif
  471.